package com.pretty.adminapp.controller.restful;

import com.google.common.collect.Lists;
import com.pretty.adminapp.dao.um.MenuDao;
import com.pretty.adminapp.pojo.base.AutoIdBaseEntity;
import com.pretty.adminapp.pojo.base.ResponseResult;
import com.pretty.adminapp.pojo.model.um.Menu;
import com.pretty.adminapp.pojo.po.AdminUserDetail;
import com.pretty.framework.common.base.PrettyDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 类描述：
 * 创建者：袁越
 * 创建日期：2017/4/15
 * 创建时间：12:19
 * Copyright:版权
 * © 2016-2020 上海金扳手科技信息股份有限公司 All rights reserved.
 */
public abstract class BaseController<T extends AutoIdBaseEntity> {
    protected Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    protected PrettyDao<T, Long> prettyDao;
    @Autowired
    private MenuDao menuDao;

    @RequestMapping(value = "/count", method = {RequestMethod.GET})
    public ResponseResult<Long> count(T po) {
        try {
            Example<T> example = Example.of(po);
            Long count = prettyDao.count(example);
            return new ResponseResult<>(count);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @RequestMapping(value = "/countAll", method = {RequestMethod.GET})
    public ResponseResult<Long> countAll() {
        try {
            Long count = prettyDao.count();
            return new ResponseResult<>(count);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @RequestMapping(value = "/getId/{aID}", method = {RequestMethod.GET})
    public ResponseResult<T> getId(@PathVariable Long aID) {
        try {
            T T = prettyDao.findOne(aID);
            return new ResponseResult<>(T);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @RequestMapping(value = "/getOne", method = {RequestMethod.GET})
    public ResponseResult<T> getOne(T po) {
        try {
            Example<T> example = Example.of(po);
            T T = prettyDao.findOne(example);
            return new ResponseResult<>(T);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @RequestMapping(value = "/getPage", method = {RequestMethod.GET})
    public ResponseResult<Page<T>> getPage(T po, PageRequest page) {
        try {
            Example<T> example = Example.of(po);
            Page<T> T = prettyDao.findAll(example, page);
            return new ResponseResult<>(T);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @RequestMapping(value = "/getAll", method = {RequestMethod.GET})
    public ResponseResult<List<T>> getAll(T po) {
        try {
            Example<T> example = Example.of(po);
            List<T> T = prettyDao.findAll(example);
            return new ResponseResult<>(T);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @RequestMapping(value = "/listAll", method = {RequestMethod.GET})
    public ResponseResult<List<T>> listAll() {
        try {
            List<T> T = prettyDao.findAll();
            return new ResponseResult<>(T);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @Transactional
    @RequestMapping(value = "/put", method = {RequestMethod.PUT})
    public ResponseResult<Long> put(@RequestBody T po) {
        try {
            po = prettyDao.save(po);
            return new ResponseResult<>(po.getId());
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @Transactional
    @RequestMapping(value = "/putBatch", method = {RequestMethod.PUT})
    public ResponseResult<List<Long>> putBatch(@RequestBody List<T> po) {
        try {
            po = prettyDao.save(po);
            List<Long> ids = Lists.newArrayList();
            for (T T : po) {
                ids.add(T.getId());
            }
            return new ResponseResult<>(ids);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @Transactional
    @RequestMapping(value = "/post", method = {RequestMethod.POST})
    public ResponseResult<Long> post(@RequestBody T po) {
        try {
            po = prettyDao.save(po);
            return new ResponseResult<>(po.getId());
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @Transactional
    @RequestMapping(value = "/postBatch", method = {RequestMethod.POST})
    public ResponseResult<List<Long>> postBatch(@RequestBody List<T> po) {
        try {
            po = prettyDao.save(po);
            List<Long> ids = Lists.newArrayList();
            for (T T : po) {
                ids.add(T.getId());
            }
            return new ResponseResult<>(ids);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @Transactional
    @RequestMapping(value = "/delete", method = {RequestMethod.DELETE})
    public ResponseResult<Long> delete(Long aID) {
        try {
            prettyDao.delete(aID);
            return new ResponseResult<>(aID);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @Transactional
    @RequestMapping(value = "/deleteBach", method = {RequestMethod.DELETE})
    public ResponseResult<List<Long>> deleteBach(List<Long> id) {
        try {
            id.forEach(it -> {
                prettyDao.delete(it);
            });
            return new ResponseResult<>(id);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    /**
     * 获取用户菜单
     *
     * @return
     */
    protected Collection<Menu> getActiveMenuList() {
        AdminUserDetail userDetail = this.getUserDetail();
        Collection<? extends GrantedAuthority> grantedAuthorities = userDetail.getAuthorities();
        Menu menu = new Menu();
        menu.setActive(true);

        Example<Menu> example = Example.of(menu);
        List<Menu> menus = menuDao.findAll(example);
        Map<Menu, List<Menu>> groupedMenus = menus.stream().filter(m -> {
                    if (m.getParent() != null) {
                        for (GrantedAuthority authority : grantedAuthorities) {
                            if (m.getPermission() != null &&
                                    authority.getAuthority().equals(m.getPermission().getCode())) {
                                return true;
                            }
                        }
                    }
                    return false;
                }
        )
                .collect(Collectors.groupingByConcurrent(Menu::getParent));
        groupedMenus.forEach((k, v) -> {
            k.setSubMenus(v);
        });
        return groupedMenus.keySet();
    }

    protected AdminUserDetail getUserDetail() {
        return (AdminUserDetail) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }

    @ModelAttribute
    public void getMenuListl(Model model) {
        model.addAttribute("menuId",1);
        model.addAttribute("menuList", this.getActiveMenuList());
    }
}
